from traits.api import HasTraits, Range, Float, Instance, \
    on_trait_change
from traitsui.api import View
from mayavi import mlab
import numpy as np
from traits.api import *
from traitsui.api import *
from mayavi.core.api import Engine
from mayavi.core.ui.api import MayaviScene, MlabSceneModel, SceneEditor
from numpy import sin, cos, mgrid, pi, sqrt


x, y, z, s = np.random.random((4, 800))
class Form(HasTraits):
    data_x_min = Float
    data_x_max = Float
    data_y_min = Float
    data_y_max = Float
    data_z_min = Float
    data_z_max = Float
    x_min = Range('data_x_min', 'data_x_max', 'data_x_min')
    x_max = Range('data_x_min', 'data_x_max', 'data_x_max')
    y_min = Range('data_y_min', 'data_y_max', 'data_y_min')
    y_max = Range('data_y_min', 'data_y_max', 'data_y_max')
    z_min = Range('data_z_min', 'data_z_max', 'data_z_min')
    z_max = Range('data_z_min', 'data_z_max', 'data_z_max')
    filter = Instance(HasTraits, allow_none=False)

    @observe('x_min,x_max,y_min,y_max,z_min,z_max')
    def update_extent(self):
        if (self.filter is not None
                and self.x_min < self.x_max
                and self.y_min < self.y_max
                and self.z_min < self.z_max
        ):
            self.filter.extent = (self.x_min, self.x_max,
                                  self.y_min, self.y_max,
                                  self.z_min, self.z_max)

    view = View('x_min', 'x_max', 'y_min', 'y_max', 'z_min', 'z_max',
                title='Edit extent', resizable=True)

fig = mlab.figure(1, bgcolor=(1, 1, 1))

pts = mlab.pipeline.scalar_scatter(x, y, z, s)
mlab.outline(pts)

geometry_filter = mlab.pipeline.user_defined(pts,
                                             filter='GeometryFilter')
geometry_filter.filter.extent_clipping = True

extent_dialog = Form(
    data_x_min=0, data_x_max=1,
    data_y_min=0, data_y_max=1,
    data_z_min=0, data_z_max=1,
    filter=geometry_filter.filter)
extent_dialog.edit_traits()
clip = mlab.pipeline.user_defined(geometry_filter,
                                  filter='CleanPolyData')
spheres = mlab.pipeline.glyph(clip, scale_factor=.1)


from PyQt5.QtWidgets import *
class FormWidget(QWidget):
    def __init__(self):
        QWidget.__init__(self)
        layout = QHBoxLayout(self)
        layout.setContentsMargins(0, 0, 0, 0)
        layout.setSpacing(0)
        self.form = Form()
        layout.addWidget(self.form.edit_traits(parent=self, kind='subpanel').control)
formWidget = FormWidget()
if __name__ == '__main__':
    import os
    import sys
    app = QApplication(sys.argv)
    formWidget.show()
    sys.exit(app.exec_())

